Imports Cdm.DataCore.Entities
Imports Cdm.DataCore.Custom
Imports System.Collections.Generic
Imports Cdm.DataCore.Admin
Imports System.IO

Partial Class DataLoad_Download
    Inherits System.Web.UI.Page

    Private Const C_REP_TABLE_ID = 14032
    Private Const C_LG_TABLE_ID = 14031
    Dim dataLoadFields As List(Of AdminDataLoadFieldList)
    Dim SpecialFieldColumnHash As Hashtable
    Dim SSNFields As ArrayList
    Dim PhoneNumberFields As ArrayList

    Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
        SetupJavaScript()
        If Not IsPostBack Then
            BindGrids()
        End If
    End Sub

    Private Sub SetupJavaScript()
        EntityController.JavaScriptAddChildDiv(Me.ParticipantDetailsScrollingGridView.DivClientId, CInt(Me.ParticipantDetailsScrollingGridView.ToolTip))
        EntityController.JavaScriptAddChildDiv(Me.ParticipantNameScrollingGridView.DivClientId, CInt(Me.ParticipantNameScrollingGridView.ToolTip))
        EntityController.JavaScriptSetFixedHeight(30)
    End Sub


    Private Sub BindGrids()
        Dim participants As List(Of ParticipantDataLoad) = ParticipantDataLoad.ListActiveByUserId(UserAuthorization.CurrentUser.UserId)
        Dim firstSpecialFieldColumn As Integer

        BuildDetailsGrid()
        firstSpecialFieldColumn = ParticipantDetailsScrollingGridView.Columns.Count
        AddSpecialFieldColumns()
        ParticipantDetailsScrollingGridView.Columns(ParticipantDetailsScrollingGridView.Columns.Count - 1).ItemStyle.Width = 160
        Me.ParticipantDetailsScrollingGridView.DataSource = participants
        Me.ParticipantNameScrollingGridView.DataSource = participants
        Me.ParticipantNameScrollingGridView.DataBind()
        Me.ParticipantDetailsScrollingGridView.DataBind()
        AddSpecialFieldValues(firstSpecialFieldColumn)
        SetDetailColumnWidths()

    End Sub

    Private Sub SetDetailColumnWidths()
        Dim maxLength As Integer
        Dim currentLength As Integer
        For iCol As Integer = 0 To Me.ParticipantDetailsScrollingGridView.Columns.Count - 1
            maxLength = 8 * ParticipantDetailsScrollingGridView.Columns(iCol).HeaderText.Length

            For iRow As Integer = 0 To Me.ParticipantDetailsScrollingGridView.Rows.Count - 1
                currentLength = ParticipantDetailsScrollingGridView.Rows(iRow).Cells(iCol).Text.Length * 6
                If currentLength > maxLength Then maxLength = currentLength
            Next

            Me.ParticipantDetailsScrollingGridView.Columns(iCol).ItemStyle.Width = CStr(maxLength)
            Me.ParticipantDetailsScrollingGridView.Columns(iCol).HeaderStyle.Width = CStr(maxLength)
        Next

        Dim lastCol As Integer = Me.ParticipantDetailsScrollingGridView.Columns.Count - 1
        Me.ParticipantDetailsScrollingGridView.Columns(lastCol).HeaderStyle.Width = _
        Me.ParticipantDetailsScrollingGridView.Columns(lastCol).ItemStyle.Width.Value + 40

    End Sub

    Private Sub AddSpecialFieldValues(ByVal firstSPColumn As Integer)
        Dim SpecialFieldValueHash As Hashtable = GetSpecialFieldValueHash
        For iRow As Integer = 0 To ParticipantDetailsScrollingGridView.Rows.Count - 1
            Dim participantidString As String = ParticipantDetailsScrollingGridView.DataKeys(iRow)(0).ToString()
            For icol As Integer = firstSPColumn To ParticipantDetailsScrollingGridView.Columns.Count - 1
                Dim adminField As AdminDataLoadFieldList = SpecialFieldColumnHash.Item(ParticipantDetailsScrollingGridView.Columns(icol).HeaderText.Replace(" (r)", ""))
                Dim tableidString As String = adminField.TableId.ToString()
                Dim fieldIdString As String = adminField.FieldId.ToString()
                Dim tableKeyString As String = GetTableKeyString(tableidString, iRow)
                Dim hashKey As String = String.Concat(fieldIdString, "||", tableKeyString, "||", tableidString)
                If SpecialFieldValueHash.ContainsKey(hashKey) Then
                    Dim spValue As SpecialFieldValue = CType(SpecialFieldValueHash.Item(hashKey), SpecialFieldValue)
                    ParticipantDetailsScrollingGridView.Rows(iRow).Cells(icol).Text = spValue.FieldValue
                Else
                    ParticipantDetailsScrollingGridView.Rows(iRow).Cells(icol).Text = ""
                End If

            Next
        Next
    End Sub

    Private Function GetTableKeyString(ByVal tableIdString As String, ByVal iRow As Integer) As String
        Dim iKey As Integer
        Select Case tableIdString
            Case C_LG_TABLE_ID
                iKey = 1
            Case C_REP_TABLE_ID
                iKey = 2
            Case Else
                iKey = 0
        End Select

        Return ParticipantDetailsScrollingGridView.DataKeys(iRow)(iKey).ToString()
    End Function

    Private Function GetSpecialFieldValueHash() As Hashtable
        Dim allvalues As IList(Of SpecialFieldValue) = SpecialFieldValue.ListAll()
        Dim valuesHash As New Hashtable
        For i As Integer = 0 To allvalues.Count - 1
            Dim valKey As String = String.Concat(allvalues(i).SpecialFieldId.ToString(), "||", allvalues(i).TableKey.ToString(), "||", allvalues(i).TableId.ToString())
            If Not valuesHash.ContainsKey(valKey) Then
                valuesHash.Add(valKey, allvalues(i))
            End If
        Next

        Return valuesHash

    End Function

    ''' <summary>
    ''' Builds the Participant Details GridView, with the following steps:
    '''     1) Clears all the columns
    '''     2) One by one, adds the columns that are in the AdminDataLoadList
    '''            a) Excludes ParticipantId, FirstName, and LastName, as these columns
    '''               are in the fixed ParticipantNameScrollingGridView
    '''            b) Retrieves the displayName from the database and sets that name
    '''                as the column header text
    '''            c) Checks if current user has update privilege on each column
    '''                If not, header text is also marked with an asterisk to show that
    '''                current user will not be able to update this column.
    ''' </summary>
    ''' <remarks></remarks>
    Private Sub BuildDetailsGrid()
        Dim bHasUpdate As Boolean
        Dim tableName As String
        Dim fieldName As String

        SSNFields = New ArrayList
        PhoneNumberFields = New ArrayList

        ParticipantDetailsScrollingGridView.Columns.Clear()
        dataLoadFields = AdminDataLoadFieldList.ListAll()
        For iField As Integer = 0 To dataLoadFields.Count - 1
            tableName = dataLoadFields(iField).TableName
            fieldName = dataLoadFields(iField).FieldName

            bHasUpdate = UserAuthorization.CurrentUser.HasFormLevelPermission(tableName, fieldName)
            Dim bIncludeInDetails as boolean=true
            
            If tableName = "Participant" Then
                Select Case fieldName
                    Case "FirstName", "LastName", "ParticipantId"
                        bIncludeInDetails = False
                    Case Else
                        bIncludeInDetails = True
                End Select
            End If

            If dataLoadFields(iField).IsSpecialField = False And bIncludeInDetails Then
                Dim newCol As New BoundField
                newCol.DataField = ParticipantDataLoad.GetFieldIdPropertyName(dataLoadFields(iField).FieldId)
                Dim tablePrefix As String
                Dim readOnlyChar As String = ""

                tablePrefix = GetTablePrefix(dataLoadFields(iField).TableId)
                If bHasUpdate = False Then readOnlyChar = " (r)"
                newCol.HeaderText = String.Concat(tablePrefix, dataLoadFields(iField).FieldDisplayName, readOnlyChar)
                newCol.ItemStyle.Width = 200
                newCol.HeaderStyle.Width = 200
                Select Case fieldName.ToLower()
                    Case "ssnumber"
                        SSNFields.Add(ParticipantDetailsScrollingGridView.Columns.Count)
                    Case "phonenumber", "phonenumber1", "phonenumber2", "faxnumber", _
                         "emergencycontactnumber"
                        PhoneNumberFields.Add(ParticipantDetailsScrollingGridView.Columns.Count)
                    Case Else
                        'Do nothing - do not add to a collection
                End Select

                ParticipantDetailsScrollingGridView.Columns.Add(newCol)
            End If
        Next

        Dim scrollScript As String
        scrollScript = String.Format("alignDivs('{0}', '{1}', '{2}');", _
                                   ParticipantDetailsScrollingGridView.DivClientId, _
                                   ParticipantNameScrollingGridView.DivClientId, _
                                   ParticipantDetailsScrollingGridView.HeaderDivClientId)
        ParticipantDetailsScrollingGridView.OnScrollJavaScript = scrollScript

    End Sub
    ''' <summary>
    ''' Adds the columns for the special field values and populates the values for each participant in 
    ''' the system.
    ''' </summary>
    ''' <remarks></remarks>
    Private Sub AddSpecialFieldColumns()
        Dim tableName As String
        Dim fieldName As String
        Dim bHasUpdate As Boolean

        SpecialFieldColumnHash = New Hashtable()

        For iField As Integer = 0 To dataLoadFields.Count - 1
            tableName = dataLoadFields(iField).TableName
            fieldName = dataLoadFields(iField).FieldName


            If dataLoadFields(iField).IsSpecialField = True Then
                Dim newCol As New BoundField
                Dim tablePrefix As String
                Dim readOnlyChar As String = ""
                tablePrefix = GetTablePrefix(dataLoadFields(iField).TableId)
                SpecialFieldColumnHash.Add(tablePrefix & dataLoadFields(iField).FieldDisplayName, dataLoadFields(iField))
                bHasUpdate = UserHasSpecialFieldPermission(dataLoadFields(iField).TableId)
                If bHasUpdate = False Then readOnlyChar = " (r)"
                newCol.HeaderText = String.Concat(tablePrefix, dataLoadFields(iField).FieldDisplayName, readOnlyChar)
                newCol.ItemStyle.Width = 200
                newCol.HeaderStyle.Width = 200
                ParticipantDetailsScrollingGridView.Columns.Add(newCol)
            End If
        Next
    End Sub

    Private Function UserHasSpecialFieldPermission(ByVal tableid As Integer) As Boolean
        Select Case tableid
            Case C_LG_TABLE_ID
                Return UserAuthorization.HasUpdatePermission(Cdm.DataCore.UserSecurity.Permission.PermissionType.CaseLegalGuardian)
            Case C_REP_TABLE_ID
                Return UserAuthorization.HasUpdatePermission(Cdm.DataCore.UserSecurity.Permission.PermissionType.CaseParticipantRep)
            Case Else
                Return UserAuthorization.HasUpdatePermission(Cdm.DataCore.UserSecurity.Permission.PermissionType.CasePersonal)
        End Select
    End Function

    Private Function GetTablePrefix(ByVal tableId As Integer) As String
        Select Case tableId
            Case C_LG_TABLE_ID
                Return "Guardian "
            Case C_REP_TABLE_ID
                Return "Rep "
            Case Else
                Return ""
        End Select
    End Function

    Protected Sub DownloadButton_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles DownloadButton.Click
        DownloadAllRows()
    End Sub

    Private Sub DownloadAllRows()
        Dim DataFileDropLocation As String = HttpContext.Current.Server.MapPath(ConfigurationManager.AppSettings.Get("SpendingPlanDrop"))
        Dim filePath As String = DataFileDropLocation + CType(Session("CurrentUserId"), String) + ".csv"
        Dim bRowsChecked As Boolean = False

        Dim downloadFile As New StreamWriter(filePath)

        WriteColumnHeadersToFile(downloadFile)
        For i As Integer = 0 To ParticipantDetailsScrollingGridView.Rows.Count - 1
            Dim rowCheckBox As CheckBox
            rowCheckBox = ParticipantNameScrollingGridView.Rows(i).FindControl("downloadCheckBox")
            If rowCheckBox.Checked Then
                WriteRowToFile(downloadFile, i)
                bRowsChecked = True
            End If
        Next

        
        downloadFile.Close()

        Dim downloadFileStream As System.IO.FileStream = New IO.FileStream(filePath, IO.FileMode.Open)
        'Dim fileSizeString As String = spFileStream.Length.ToString()
        'spFileStream.Close()
        Dim fileByteLength As String = downloadFileStream.Length.ToString()
        downloadFileStream.Close()
        downloadFileStream = Nothing

        If bRowsChecked Then

            Response.ClearContent()
            Response.ClearHeaders()
            Response.Clear()
            Response.ContentType = "text/csv" '"application/vnd.ms-excel"
            Response.AddHeader("content-length", fileByteLength)
            Response.AddHeader("Content-Disposition", "attachment;filename=DataDownload.csv") '& t_ExpenditureFileName)
            Response.AddHeader("Target", "newwindow")
            Response.WriteFile(filePath)
        Else
            Response.Write("<script language=""javascript"">alert('Please check at least one row to include in your download.  Click the Set All box at the top to select all rows.');</script>")
        End If
    End Sub

    Private Sub WriteRowToFile(ByVal fl As StreamWriter, ByVal iRow As Integer)
        For iName As Integer = 1 To ParticipantNameScrollingGridView.Columns.Count - 1
            fl.Write(CleanText(ParticipantNameScrollingGridView.Rows(iRow).Cells(iName).Text))
            fl.Write(",")
        Next

        Dim lastCol As Integer = ParticipantDetailsScrollingGridView.Columns.Count - 1
        For iDetail As Integer = 0 To lastCol
            fl.Write(CleanText(ParticipantDetailsScrollingGridView.Rows(iRow).Cells(iDetail).Text))
            If iDetail < lastCol Then
                fl.Write(",")
            Else
                fl.WriteLine()
            End If
        Next
    End Sub

    Private Sub WriteColumnHeadersToFile(ByVal fl As StreamWriter)
        For iName As Integer = 1 To ParticipantNameScrollingGridView.Columns.Count - 1
            fl.Write(CleanText(ParticipantNameScrollingGridView.Columns(iName).HeaderText))
            fl.Write(",")
        Next

        Dim lastCol As Integer = ParticipantDetailsScrollingGridView.Columns.Count - 1
        For iDetail As Integer = 0 To lastCol
            fl.Write(CleanText(ParticipantDetailsScrollingGridView.Columns(iDetail).HeaderText))
            If iDetail < lastCol Then
                fl.Write(",")
            Else
                fl.WriteLine()
            End If
        Next
    End Sub

    ''' <summary>
    ''' Returns the input text, suitable for csv.
    ''' Rules:  1) Sometimes the text in the grid is a space, except html encoded <PRE>(nbsp;)</PRE>
    '''         This needs to be HTMLDecoded.
    '''         2) Trim the overall value
    '''         3) place all values in quotes, to handle the case where a value has a comma within it.
    '''         4) If a value has a quote within it double the quote so the file knows not
    '''            to end the cell at the first quote.
    '''         
    ''' </summary>
    ''' <param name="inputText">string with the value to clean</param>
    ''' <returns>string - cleaned version of the input string</returns>
    ''' <remarks></remarks>
    Private Function CleanText(ByVal inputText As String) As String
        Dim C_QUOTE As Char = Chr(34)
        Dim C_DBL_QUOTE As Char = Chr(34) & Chr(34)
        Dim C_TICK As Char = "'"

        Dim decodedText As String = Server.HtmlDecode(inputText).Trim()
        Dim quotedText = String.Concat(C_QUOTE, decodedText.Replace(C_QUOTE, C_DBL_QUOTE), C_QUOTE)

        Return quotedText

    End Function

    Protected Sub ParticipantDetailsScrollingGridView_RowDataBound(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.GridViewRowEventArgs) Handles ParticipantDetailsScrollingGridView.RowDataBound
        Try
            If e.Row.RowIndex >= 0 Then
                Dim iCol As Integer
                Dim formattedCellText As String
                For i As Integer = 0 To SSNFields.Count - 1
                    iCol = CInt(SSNFields(i))
                    formattedCellText = FormatSSN(e.Row.Cells(iCol).Text)
                    e.Row.Cells(iCol).Text = formattedCellText
                Next

                For i As Integer = 0 To PhoneNumberFields.Count - 1
                    iCol = CInt(PhoneNumberFields(i))
                    formattedCellText = FormatPhone(e.Row.Cells(iCol).Text.Trim())
                    e.Row.Cells(iCol).Text = formattedCellText
                Next

            End If
        Catch ex As Exception

        End Try
    End Sub

    Private Function FormatSSN(ByVal ssn As String) As String
        If String.IsNullOrEmpty(ssn) Then
            Return ""
        ElseIf ssn.Length < 9 Then
            Return ssn
        Else
            Return String.Concat(ssn.Substring(0, 3), "-", ssn.Substring(3, 2), "-", ssn.Substring(5))
        End If
    End Function

    Private Function FormatPhone(ByVal phone As String) As String

        Select Case phone.Length
            Case Is < 7
                Return phone
            Case 7
                Return String.Concat(phone.Substring(0, 3), "-", phone.Substring(3))
            Case 10
                Return String.Concat("(", phone.Substring(0, 3), ") ", phone.Substring(3, 3), "-", phone.Substring(6))
            Case Else
                Return phone
        End Select
    End Function
End Class
